package sporteam.web.server;

import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Logger;
import javax.jdo.JDOException;
import javax.jdo.PersistenceManager;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sporteam.common.PMF;
import sporteam.web.client.AEuser;
import sporteam.web.client.Activity;
import sporteam.web.client.GeoPtr;
import sporteam.web.client.Track;
import sporteam.web.client.UserAppData;

import com.restfb.Connection;
import com.restfb.DefaultFacebookClient;
import com.restfb.FacebookClient;

@SuppressWarnings("serial")
public class RegisterFacebook extends HttpServlet {
	private static final Logger MyLog = Logger.getLogger(UpdateUser.class
			.getName());

	@Override
	public void doGet(HttpServletRequest req, HttpServletResponse res)
			throws IOException {
		String facebook_access_token = req.getParameter("access_token");
		String facebook_code = req.getParameter("code");

		AEuser ae_user = createFacebookUser(facebook_code,
				facebook_access_token);

		// create a new user only if user doesn't exist in the DB
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			pm.getObjectById(AEuser.class, ae_user.GetFacebookID());
			MyLog.warning("User found in Datastore.");
		} catch (JDOException ex) {
			MyLog.warning("User not found in the Datastore. Creating new user and updating friend_lists...");;
			updateFriendList(ae_user, facebook_access_token);
			//debug purposes
			//barmako and tester jones facebook-ids
			if(ae_user.GetFacebookID().equals("1507604362") || ae_user.GetFacebookID().equals("100003730751502")){	
				ae_user.AddActivity(madeUpActivity());
			}
			pm.makePersistent(ae_user);
			pm.close();
			
			
			
			
			//add UserAppData aswell.
			try{
			UserAppData.addUserAppDataToDataStore(ae_user.GetFacebookID());
			}
			catch(Exception e){
				MyLog.warning("Exception while adding UserAppData");
			}

		}
		
		
		//TODO if its users first visit promot him to update info page first.

		res.sendRedirect("/myHomepage.html?access_token="
				+ facebook_access_token);
	}

	private AEuser createFacebookUser(String code, String access_token) {
		// establish connection with facebook-graph API with a specific
		// access_token
		FacebookClient facebookClient = new DefaultFacebookClient(access_token);
		com.restfb.types.User facebook_user = facebookClient.fetchObject("me",
				com.restfb.types.User.class); // me - the facebook user logged
												// in ATM.

		AEuser u = new AEuser();

		// Set the new user attributes.
		String[] name = facebook_user.getName().split(" ");
		String first_name = name[0].trim();
		String last_name = name[1].trim();
		u.SetFacebookID(facebook_user.getId());
		u.setFacebook_code(code);
		u.SetFirstName(first_name);
		u.SetLastName(last_name);
		u.SetGender(facebook_user.getGender());
		u.SetEmail(facebook_user.getEmail());
		u.UpdateDate();
		u.SetAge(ComputeAge(facebook_user.getBirthday()));
		return u;
	}

	

	private int ComputeAge(String birthday)
	{
		return 20; // default
	}

	private void updateFriendList(AEuser u, String access_token) {
		// establish connection with facebook-graph API with a specific
		// access_token
		FacebookClient facebookClient = new DefaultFacebookClient(access_token);

		com.restfb.types.User facebook_user = facebookClient.fetchObject("me",
				com.restfb.types.User.class); // me - the facebook user logged
												// in ATM.
		Connection<com.restfb.types.User> myFriends = facebookClient
				.fetchConnection("me/friends", com.restfb.types.User.class);
		PersistenceManager pm = PMF.get().getPersistenceManager();

		// make default in activity to be false
		String InActivityStr = "not_in_act";
		
		for (com.restfb.types.User friend : myFriends.getData()) {
			try {
				AEuser ae_user = pm.getObjectById(AEuser.class, friend.getId());

				// add friend to my friends_list
				u.addSporteamFriend(friend.getId() + ";" + friend.getName()
						+ ";" + InActivityStr + ";");

				// add myself too each friend's friend_list as well
				ae_user.addSporteamFriend(facebook_user.getId() + ";"
						+ facebook_user.getName() + ";" + InActivityStr + ";");

				ae_user.UpdateDate();
				pm.makePersistent(ae_user);

				MyLog.warning("added sporteam friend: " + friend.getId() + "in act status: " + InActivityStr);
			} catch (Exception e) {
				// Do nothing
			}
		}
		pm.close();
	}

	// check if the user and the current friend share an activity
	private boolean FindSharedActivity(AEuser ae_user, String friendID) {
		ArrayList<Activity> activities = ae_user.GetActivities();

		for (Activity act : activities) {
			if (act.getSenderID().equals(friendID)
					&& act.getReceiverTrack() == null) {
				return true;
			}
			if (act.getReceiverID().equals(friendID)
					&& act.isClosedActivity()) {
				return false;
			}
		}

		return false;
	}

	private ArrayList<GeoPtr> madeUpTrackList() {
		ArrayList<GeoPtr> returnList = new ArrayList<GeoPtr>();
		for (int i = 1; i <= 30; i++) {
			returnList.add(new GeoPtr(31.974 + i * 0.001
					* (Math.random() * 2 - 1), 34.813 - i * 0.001
					* (Math.random() * 2 - 1), 0, 0, 0));
		}
		return returnList;
	}
	private Activity madeUpActivity() {
		Track senderTrack = new Track(10, 10, 10, 10, madeUpTrackList());
		senderTrack.setName("sender");
		Track receiverTrack = new Track(11, 11, 11, 11, madeUpTrackList());
		receiverTrack.setName("receiver");
		Activity activity = new Activity(senderTrack, "1507604362",
				"100003730751502", "sender", "receiver");
		activity.setReceiverTrack(receiverTrack);

		return activity;
	}
}
